package dao;

import dto.PacienteDTO;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.time.LocalDate;
import java.util.ArrayList;

/**
 *
 * @author lucifer
 */
public class PacienteDAO {

  public static final String Tab =
    "create table paciente (" +
    "id serial," + //pk
    "nombre text," +
    "apellido text," +
    "dni int," +
    "fecha_nac date," +
    "id_obra_social int," + //fk
    "id_plan_obra_social int," + //fk
    "n_afiliado int," +
    "direccion text," +
    "tel_linea text," +
    "celular text," +
    "email text," +
    "contacto_nombre text," +
    "contacto_apellido text," +
    "contacto_telefono text" +
    ");" +

    "alter table paciente add constraint paciente_obra_social_fk foreign key (id_obra_social) references obra_social(id);" +
    "alter table paciente add constraint paciente_plan_obra_social_fk foreign key (id_plan_obra_social) references obra_social_plan(id);"
  ;

  public static final String Tuples = "";
    /*
"insert into paciente (nombre,apellido,dni,fecha_nac,id_obra_social,id_plan_obra_social,n_afiliado,direccion,tel_linea,celular,email,contacto_nombre,contacto_apellido,contacto_telefono) values" +
"('Ken', 'Thompson', 5153057, '1995-05-05', 7, 25, 9248, 'Av. Rivadavia 3855, Almagro, Capital Federal', '30462-1160', '15-2889-7948', 'ken@thompson.org', 'Dennis', 'Ritchie', '03853-8812')," +
"('Dennis', 'Ritchie', 25610126, '1955-04-11', 1, 3, 1722, 'Av. Rivadavia 5730, Caballito, Capital Federal', '03853-8812', '15-7811-5045', 'dennis@ritchie.org', 'Ken', 'Thompson', '15-2889-7948')," +
"('Donald', 'Knuth', 9168297, '1984-04-05', 2, 4, 2578, 'Colombres y Nicaragua, Avellaneda, Buenos Aires', '20798-9394', '15-2780-6005', 'don@knuth.org', 'Douglas', 'McIlroy', '15-9625-0245')," +
"('Rob', 'Pike', 4915593, '1946-08-16', 1, 1, 4157, 'Av. Vergara 1900, Morón, Buenos Aires', '33629-2417', '15-1114-9719', 'rob@pike.org', 'Brian', 'Kernighan', '3506-8927')," +
"('Douglas', 'McIlroy', 33187055, '1939-06-09', 2, 5, 5925, 'Alvear 2486 al 2500, Villa Ballester, Buenos Aires', '7199-6865', '15-9625-0245', 'douglas@mcilroy.org', 'Donald', 'Knuth', '15-2780-6005')," +
"('Brian', 'Kernighan', 13897948, '1992-11-22', 4, 14, 6609, 'H. Yrigoyen 13200, Adrogué, Buenos Aires', '3506-8927', '15-6410-6066', 'brian@kernighan.org', 'Rob', 'Pike', '33629-2417')," +
"('Bill', 'Joy', 34115045, '1954-02-04', 1, 1, 5418, 'Brown 266, Bahía Blanca, Buenos Aires', '3328-7229',  '15-4215-8655', 'bill@joy.org', 'Marshall Kirk', 'McKusick', '4863-0806')," +
"('Marshall Kirk', 'McKusick', 9806005, '1995-12-27', 0, 0, 0, 'Av. Cabildo 2254, Belgrano, Capital Federal', '4863-0806', '15-5197-4379', 'marshall_kirk@mckusick.org', 'Bill', 'Joy', '15-4215-8655')," +
"('Theo', 'de Raadt', 5149719, '1950-02-07', 7, 24, 6434, 'Av. O''Higgins y Calle Calmayo, Córdoba, Córdoba', '05968-6679', '15-6470-9444', 'theo@deraadt.org', 'Susana', 'Giménez', '6375-6150')," +
"('Cristina', 'Kirchner', 6250245, '1990-08-17', 5, 20, 1213, 'Gral. Urquiza 4785, Caseros, Gran Bs. As. Oeste', '8386-9090', '15-5291-0113', 'cfk@fpv.gov.ar', 'Hugo', 'Chávez', '9699-2330')," +
"('Hugo', 'Chávez', 35106066, '1921-05-22', 3, 6, 4388, 'Av. Sacalabrini Ortiz 3149, Palermo, Capital Federal', '9699-2330', '15-3254-7862', 'hugo@chavez.gov.ve', 'Cristina', 'Kirchner', '15-5291-0113')," +
"('Diego', 'Maradona', 19158655, '1985-02-27', 6, 23, 3529, 'Av. Santa Rosa esq. Sarmiento, Castelar, Buenos Aires', '8584-8397', '15-3361-4854', 'diego@dios.com.ar', 'Martín', 'Palermo', '2881-6307')," +
"('Martín', 'Palermo', 5974379, '1918-06-09', 7, 24, 7763, 'Av. Córdoba y Caferatta, Rosario, Santa Fe', '2881-6307', '15-9877-3169', 'martin@palermo.com.ar', 'Diego', 'Maradona', '15-3361-4854')," +
"('Carlos', 'Tévez', 8709444, '1965-05-13', 6, 23, 9684, 'Cabildo 742, Palermo, Capital Federal', '4814-1429', '15-6659-3625', 'carlitos@tevez.com.ar', 'Susú', 'Pecoraro', '15-6695-9505')," +
"('Guillermo', 'Barros Schelotto', 3910113, '1982-05-03', 2, 5, 5081, 'Av. Constitución 7570, Mar del Plata, Buenos Aires', '5733-1172',  '15-5020-5695', 'guille@melli.com.ar', 'Carlos', 'Tévez', '4814-1429')," +
"('Susú', 'Pecoraro', 7547862, '1935-04-03', 0, 0, 0, 'Perón 989, San Miguel, San Miguel, Buenos Aires', '3317-7181', '15-6695-9505', 'susu@pecoraro.com.ar', 'Nacha', 'Guevara', '15-3200-5513')," +
"('Norma', 'Aleandro', 26614854, '1992-03-18', 6, 21, 9170, 'Av. Colón esq. Bmé. Mitre, Mendoza, Mendoza', '3331-0137', '15-9155-4115', 'norma@aleandro.com.ar', 'Susú', 'Pecoraro', '15-6695-9505')," +
"('Soledad', 'Silveyra', 7773169, '1957-07-28', 0, 0, 0, 'Av. Corrientes 2558, Balvanera, Capital Federal', '7944-9276', '15-9184-4522', 'sole@silveyra.com.ar', 'Susú', 'Pecoraro', '15-6695-9505')," +
"('Susana', 'Giménez', 28593625, '1944-06-05', 4, 19, 7921, 'Av. Santa Fé 2468/70, Recoleta, Capital Federal', '6375-6150', '15-7946-8164', 'su@gimenez.com.ar', 'Nacha', 'Guevara', '15-3200-5513')," +
"('Libertad', 'Lamarque', 32205695, '1971-03-07', 6, 22, 3325, 'Av. Don Bosco 2680, L.25, San Justo, Buenos Aires', '8626-6771', '15-6363-9690', 'libertad@lamarque.com.ar', 'Ana María', 'Picchio', '5257-9261')," +
"('Ana María', 'Picchio', 19020903, '1946-08-06', 1, 2, 9855, 'Ruta 8 y Ruta 202, San Miguel, San Miguel, Buenos Aires', '5257-9261', '15-4819-2117', 'ana.maria@picchio.com.ar', 'Susú', 'Pecoraro', '15-6695-9505')," +
"('Nacha', 'Guevara', 39202905, '1995-09-10', 3, 7, 4017, 'Av. Centenario 72, San Isidro, San Isidro, Buenos Aires', '2205-4242', '15-3200-5513', 'nacha@guevara.com', 'Ana María', 'Picchio', '5257-9261')," +
"('Niní', 'Marshall', 10535508, '1951-09-07', 0, 0, 0, 'Av. Antártida Arg. 703, Lomas de Zamora, Buenos Aires', '8950-2078', '15-9799-6045', 'nini@marshall.com', 'Libertad', 'Lamarque', '15-6363-9690')," +
"('Claudia', 'Lapacó', 30934609, '1961-08-03', 3, 8, 5013, 'Av. Las Heras 3215, Palermo, Capital Federal', '4421-5228', '15-2005-4879', 'claudia@lapaco.com.ar', 'Nacha', 'Guevara', '15-3200-5513');" ;
  */

  private static PacienteDAO dao = null;
  private final Connection c;

  public static PacienteDAO createDAO() throws SQLException  {
    if (dao == null) {
      dao = new PacienteDAO();
    }
    return dao;
  }

  private PacienteDAO() throws SQLException {
    c = DB.PQ().Conn();
  }

  public int LastID() throws SQLException {
    return DB.PQ().LastIDFrom("paciente");
  }

  public ArrayList<PacienteDTO> All() throws SQLException {
    return getPacienteDTOs("select * from paciente order by apellido, nombre, dni;");
  }

  public ArrayList<PacienteDTO> SearchByNombreApellido(String s) throws SQLException {
    validNombreApellido(s);
    return getPacienteDTOs(queryByNombreApellido(s));
  }

  public ArrayList<PacienteDTO> SearchByDNI(int dni) throws SQLException {
    return getPacienteDTOs(queryByDNI(dni));
  }

  private String queryByNombreApellido(String name) throws SQLException {
    String query = String.format(
      "select * from paciente where nombre ~* '^%s' or apellido ~* '^%s' order by apellido, nombre, dni;",
      name, name
    );
    return query;
  }

  private String queryByDNI(int dni) throws SQLException {
    String query = String.format(
      "select * from paciente where cast(dni as text) ~* '^%d' order by dni;", dni
    );
    return query;
  }

  // FIXXXME!!!
  private void validNombreApellido(String name) {
  }

  private ArrayList<PacienteDTO> getPacienteDTOs(String query) throws SQLException {
    Statement s = c.createStatement();
    ResultSet r = s.executeQuery(query);
    ArrayList<PacienteDTO> pacientes = new ArrayList<>();
    while (r.next()) {
      pacientes.add(
        new PacienteDTO(
          r.getInt("id"),
          r.getString("nombre"),
          r.getString("apellido"),
          r.getInt("dni"),
          LocalDate.parse(r.getString("fecha_nac")),
          r.getInt("id_obra_social"),
          r.getInt("id_plan_obra_social"),
          r.getInt("n_afiliado"),
          r.getString("direccion"),
          r.getString("tel_linea"),
          r.getString("celular"),
          r.getString("email"),
          r.getString("contacto_nombre"),
          r.getString("contacto_apellido"),
          r.getString("contacto_telefono")
        )
      );
    }
    r.close();
    s.close();
    return pacientes;
  }

  public PacienteDTO PacienteDTO(int id) throws SQLException {
    Statement s = c.createStatement();
    ResultSet r = s.executeQuery(
      "select * from paciente where id = " + id
    );
    PacienteDTO dto = null;
    if (r.next()) {
      dto = new PacienteDTO(
        r.getInt("id"),
        r.getString("nombre"),
        r.getString("apellido"),
        r.getInt("dni"),
        LocalDate.parse(r.getString("fecha_nac")),
        r.getInt("id_obra_social"),
        r.getInt("id_plan_obra_social"),
        r.getInt("n_afiliado"),
        r.getString("direccion"),
        r.getString("tel_linea"),
        r.getString("celular"),
        r.getString("email"),
        r.getString("contacto_nombre"),
        r.getString("contacto_apellido"),
        r.getString("contacto_telefono")
      );
    }
    r.close();
    s.close();
    return dto; //si no existe devuelve null
  }

  // Guarda un **nuevo** paciente.
  // Este método tiene un bug: si dos usuarios distintos crean un paciente cada
  // uno al mismo tiempo, puede que el id que se le asigna al pacienteDTO quede
  // desfasado. Por el momento, vamos a suponer que eso no va a pasar nunca.
  public int SaveNew(PacienteDTO p) throws SQLException {
    String query = String.format(
      "insert into paciente values (default, '%s', '%s', %d, '%s', %d, %d, %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s');",
      p.getNombre(), p.getApellido(), p.getDni(), p.getFechaNac(), p.getIdObraSocial(), p.getIdPlanObraSocial(), p.getNAfiliado(), p.getDireccion(), p.getTelLinea(), p.getCelular(), p.getEmail(), p.getContactoNombre(), p.getContactoApellido(), p.getContactoTelefono()
    );
    Statement s = c.createStatement();
    s.executeUpdate(query);
    s.close();
    return LastID(); // pequeño bug, leer más arriba
  }

  public void Update(PacienteDTO p) throws SQLException {
    String query = String.format(
      "update paciente set nombre = '%s', apellido = '%s', dni = %d, fecha_nac = '%s', id_obra_social = %d, id_plan_obra_social = %d, n_afiliado = %d, direccion = '%s', tel_linea = '%s', celular = '%s', email = '%s', contacto_nombre = '%s', contacto_apellido = '%s', contacto_telefono = '%s' where id = %d;",
      p.getNombre(), p.getApellido(), p.getDni(), p.getFechaNac(), p.getIdObraSocial(), p.getIdPlanObraSocial(), p.getNAfiliado(), p.getDireccion(), p.getTelLinea(), p.getCelular(), p.getEmail(), p.getContactoNombre(), p.getContactoApellido(), p.getContactoTelefono(), p.getId()
    );
    Statement s = c.createStatement();
    s.executeUpdate(query);
    s.close();
  }

  // Modifica un atributo de tipo string en un paciente, incluida la fecha.
  public PacienteDTO EditString(int id, String attr, String str) throws SQLException {
    String query = String.format(
      "update paciente set %s = '%s' where id = %d;",
      attr, str, id
    );
    Statement s = c.createStatement();
    s.executeUpdate(query);
    s.close();
    return PacienteDTO(id);
  }

  // Modifica un atributo de tipo int en un paciente.
  public PacienteDTO EditInt(int id, String attr, int n) throws SQLException {
    String query = String.format(
      "update paciente set %s = %d where id = %d;",
      attr, n, id
    );
    Statement s = c.createStatement();
    s.executeUpdate(query);
    s.close();
    return PacienteDTO(id);
  }

}
